=begin rdoc
Unit tests for rupeas class.

Author::    Matthias Woehrle  (mailto:matthias.woehrle@tik.ee.ethz.ch)
Copyright:: Copyright (c) 2008 ETH Zurich
License::   

TODO:

MISSING:
=end

$:.unshift File.join(File.dirname(__FILE__), "..", "lib")

require 'rupeas'
require 'test/unit'
require 'rubygems'
require 'mocha'

class MockFile < Array
  def write(string)
    self << string.to_s
  end
  def close()
    puts "Closed Mockfile" if $DEBUG
  end  
end

class TestRupeasDefinition < Test::Unit::TestCase

  #test that there are no exceptions on use
  def test_init_should_result_in_nothin_raised
    assert_nothing_raised {
    Rupeas.new do
    end
    }
  end

  def test_init_should_be_able_to_create_a_new_event_of_the_type_with_nothing_raised
    assert_nothing_raised do
      Rupeas.new do
      Type :senddone do
       with :name=>:ack, :fieldtype => :integer,  :range => [0,1],:notification => :warning
       with :name=>:nodeid, :fieldtype => :integer, :range => [0, 2, 5, 7, 10, 11, 21, 26, 29, 30, 33, 40, 41, 42, 43, 44, 60, 61], :notification => :warning
       with :name=>:mine,:fieldtype=> :string
      end
      end
      assert_equal(Event.new(:type=>:senddone, :ack=>1, :nodeid=>2, :mine=>"something"), Rupeas::Senddone.new([1,2,"something"]))
    end 
  end
  
  #define three types and read in a mocked log with different fields types and soforth
  def test_init_and_loadlog_should_return_stubbed_events
    all = EventSet.new
    Rupeas.new do

    Type :senddone do
     with :name=>:ack, :fieldtype => :integer,  :range => [0,1],:notification => :warning
     with :name=>:nodeid, :fieldtype => :integer, :range => [0, 2, 5, 7, 10, 11, 21, 26, 29, 30, 33, 40, 41, 42, 43, 44, 60, 61], :notification => :warning
     with :name=>:mine,:fieldtype=> :string
    end


    Type :received do
     with :name=>:nodeid, :fieldtype => :integer, :range => [0, 2, 5, 7, 10, 11, 21, 26, 29, 30, 33, 40, 41, 42, 43, 44, 60, 61], :notification => :warning
     with :name=>:seqNo, :fieldtype=> :integer, :range => 0..255, :notification => :error
    end

    Type :measure do
     with :name=>:nodeid, :fieldtype => :integer, :range => [0, 2, 5, 7, 10, 11, 21, 26, 29, 30, 33, 40, 41, 42, 43, 44, 60, 61], :notification => :warning
     with :name=>:measured, :fieldtype => :float, :range => {:upper=>1.0, :lower=>-12.3} , :notification => :warning
    end

    thislist = [
      "received 40 40",
      "received 40 255",
      "senddone 1 0 hello",
      "senddone 1 11 hello",
      "senddone 1 60 hello",
      "measure 60 -12"
      ]
    File.stubs(:open).returns(thislist)
    #File open is stubbed so open any dile

    all = loadlog('../test_rupeas.rb')
   end
   assert_equal(6, all.length)
   assert_equal(1, all[:type=>:measure].length)
   assert_equal(2, all[:type=>:received].length)
   assert_equal(3, all[:type=>:senddone].length)

  end


  def test_savelog_should_return_stubbed_event_and_description_file_in_arrays
   f  = EventSet.new()
   alist = MockFile.new
   blist = MockFile.new
   eventinput = [
   "sending 3 1",
   "sending 3 2",
   "sending 3 3",
   "receive 3 1",
   "receive 4 1",
   "meas 5 12"]    
   
   File.stubs(:open).with('p1.red', 'w').returns(alist)
   File.stubs(:open).with('p1.log', 'w').returns(blist)  
   File.stubs(:open).with('loadlog.file').returns(eventinput)
   
    Rupeas.new do

      Type :sending do
       with :name=>:nodeid, :fieldtype => :integer
       with :name=>:origin, :fieldtype => :integer
      end

      Type :receive do
       with :name=>:nodeid, :fieldtype => :integer
       with :name=>:origin, :fieldtype=> :integer
      end

      Type :meas do
       with :name=>:nodeid, :fieldtype => :integer
       with :name=>:temp, :fieldtype => :float
      end
    
      f = loadlog('loadlog.file')
     savelog(f, 'p1')
#     alist.each {|item| puts item + "\n"}
#     blist.each {|item| puts item + "\n"}
    end
    aref=["Rupeas.new do\n",
      "  Type :meas do\n",  "    with :name => :nodeid, :fieldtype => :integer\n",
      "    with :name => :temp, :fieldtype => :float\n","  end\n",
          "  Type :receive do\n", "    with :name => :origin, :fieldtype => :integer\n",
           "    with :name => :nodeid, :fieldtype => :integer\n","  end\n",
           "  Type :sending do\n","    with :name => :origin, :fieldtype => :integer\n",
           "    with :name => :nodeid, :fieldtype => :integer\n","  end\n",
           "end"]

    bref = ["sending 3 2\n","sending 3 1\n","receive 3 1\n","sending 3 3\n",
            "meas 5 12.0\n","receive 4 1\n"]
    assert_equal(aref.length, alist.length)
    aref.each {|item| assert(alist.include?(item), "expected\n#{item}\nBut it is not in :\n#{alist}")}

    assert_equal(bref.length, blist.length)
    bref.each {|item| assert(blist.include?(item), "expected\n#{item}\nBut it is not in :\n#{blist}")}
  end
end

class TestRupeasTransformation < Test::Unit::TestCase
  def setup
     @reference_origin = EventSet.new
     @success = EventSet.new
     @g  = EventSet.new
     @send1 = Event.new(:nodeid => 3, :type => :senddone, :origin=> 3, :destination=>4, :time =>3)
     @send2 = Event.new(:nodeid => 4, :type => :senddone, :origin=> 3, :destination=>5, :time => 10)
     @send3 = Event.new(:nodeid => 5, :type => :senddone, :origin=> 3, :destination=>20, :time => 10)
     @receive1 = Event.new(:nodeid => 4, :type => :receive, :origin=> 3, :destination=>4, :time => 11)
     @receive2 = Event.new(:nodeid => 5, :type => :receive, :origin=> 3, :destination=>5, :time => 11)
     @receive3 = Event.new(:nodeid => 20, :type => :receive, :origin=> 3, :destination=>20, :time => 12)
     @receive4 = Event.new(:nodeid => 20, :type => :receive, :origin=> 3, :destination=>20, :time => 12)
     @receive5 = Event.new(:nodeid => 20, :type => :receive, :origin=> 3, :destination=>20, :time => 13)   
     @send_succ1 = Event.new(:nodeid => 3, :type => :send_success, :origin=> 3, :destination=>4, :time =>3)
     @send_succ2 = Event.new(:nodeid => 4, :type => :send_success, :origin=> 3, :destination=>5, :time => 10)
     @send_succ3 = Event.new(:nodeid => 5, :type => :send_success, :origin=> 3, :destination=>20, :time => 10)
     @receive_succ1 = Event.new(:nodeid => 4, :type => :receive_success, :origin=> 3, :destination=>4, :time => 11)
     @receive_succ2 = Event.new(:nodeid => 5, :type => :receive_success, :origin=> 3, :destination=>5, :time => 11)
     @receive_succ3 = Event.new(:nodeid => 20, :type => :receive_success, :origin=> 3, :destination=>20, :time => 12) 
     @g.merge([@send1, @send2, @send3, @receive1, @receive2, @receive3])
     @origin_transformed= Event.new(:nodeid => 3, :type => :route, :origin=> 3, :destination=>4, :time =>3)
     @reference_origin.merge([@origin_transformed, @send2, @send3, @receive1, @receive2, @receive3])
     @success.merge([@send_succ1, @send_succ2, @send_succ3, @receive_succ1, @receive_succ2, @receive_succ3])     
  end
  
  def test_new_transform_single_event_that_it_outputs_right_amount_of_events
      routestart = @g.transform do |sending|
        constraint sending[:origin] == sending[:nodeid]       # partition
        constraint sending[:type] == :senddone                # filter
        create1 :type => :route,:nodeid => sending[:nodeid],:seqNo => sending[:seqNo],:origin => sending[:origin], :time => sending[:time]
      end      
      assert_equal(@reference_origin.length, routestart.length)
  end
  

  def test_new_transform_single_event_that_it_outputs_correct_events
      routestart = @g.transform do |sending|
        constraint sending[:origin] == sending[:nodeid]       # partition
        constraint sending[:type] == :senddone                # filter
        create1 :type => :route,:nodeid => sending[:nodeid],:origin => sending[:origin], :destination => sending[:destination], :time => sending[:time]
      end      
      @reference_origin.each do |event|
        assert(routestart.include?(event), "#{event} should be found in result #{routestart}")
      end
  end

  
  def test_new_transform_multiple_events_returns_the_right_amount_of_events
      routestart = @g.transform do |sending, receive|
        constraint sending[:type] == :senddone
        constraint receive[:type] == :receive        
        constraint sending[:origin] == receive[:origin]
        constraint sending[:dest] == receive[:nodeid]
        create1 :type => :send_success, :origin => sending[:origin],:nodeid   => sending[:nodeid], :destination => sending[:destination], :time => receive[:destination]
        create2 :type => :receive_success, :origin => receive[:origin], :nodeid   => receive[:nodeid], :destination => sending[:destination], :time => receive[:destination]
      end
      assert(@success.length, routestart.length)
  end

  def test_new_transform_multiple_events_returns_the_correct_events
    routestart = @g.transform do |sending, receive|
       constraint sending[:type] == :senddone
       constraint receive[:type] == :receive        
       constraint sending[:origin] == receive[:origin]
       constraint sending[:destination] == receive[:nodeid]
       create1 :type => :send_success, :origin => sending[:origin],:nodeid   => sending[:nodeid], :destination => sending[:destination], :time => sending[:time]
       create2 :type => :receive_success, :origin => receive[:origin], :nodeid   => receive[:nodeid], :destination => sending[:destination], :time => receive[:time]
     end
     @success.each do |event|
       assert(routestart.include?(event), "#{event} should be found in result #{routestart}")
     end
  end
end

#For accessing private methods
#http://blog.jayfields.com/2007/11/ruby-testing-private-methods.html
class Class
   def publicize_methods
     saved_private_instance_methods = self.private_instance_methods
     self.class_eval { public *saved_private_instance_methods }
       yield
     self.class_eval { private *saved_private_instance_methods }
   end
end
  
class TestEventSetInternal < Test::Unit::TestCase

  def setup
    @e  = EventSet.new()
    @f  = EventSet.new()
    @e1 = Event.new(:nodeid => 3, :type => :send, :origin=> 1)
    @e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
    @e3 = Event.new(:nodeid => 3, :type => :send, :origin=> 3)
    @e4 = Event.new(:nodeid => 3, :type => :send, :origin=> 4)
    @list = Array.new()
    @e.add(@e1)
    @e.add(@e2)
    @e.add(@e3)
    @e.add(@e4)
    f1 = EventSet.new()
    f1<<(@e1)
    f1<<(@e2)
    f1<<(@e3)     
    @list << f1
    f2 = EventSet.new()
    f2<<(@e1)
    f2<<(@e2)
    f2<<(@e4)     
    @list << f2
    f3 = EventSet.new()
    f3<<(@e1)
    f3<<(@e3)
    f3<<(@e4)     
    @list << f3
    f4 = EventSet.new()
    f4<<(@e2)
    f4<<(@e3)
    f4<<(@e4)
    @list << f4
    
  end
        
  def test_ksubn_should_provide_not_more_events_check_length

    #need to create eventsetlist so it is used in the block below
    eventsetlist = []
    leftover = nil
    EventSet.publicize_methods do
      eventsetlist, leftover = @e.ksubn(3)
    end
    assert_equal(@list.length, eventsetlist.length)
   end 
   
   #test the ksubn private method return k subsets of an n element set
   def test_ksubn_should_provide_all_events_in_list

     #need to create eventsetlist so it is used in the block below
     eventsetlist = []
     leftover = nil
     EventSet.publicize_methods do
       eventsetlist, leftover = @e.ksubn(3)
     end
     i=0
     eventsetlist.each do |x|
        assert(@list.include?(x),"result #{x} not in the reference #{@list} in #{i}th iteration")
     end
   end
   def test_ksubn_iterator_should_provide_not_more_events_check_length
       filterset = EventSet.new()
       i=0
       EventSet.publicize_methods do
          @e.ksubn_iterator(3) do |x|
            i=i+1
          end
       end
       assert_equal(@list.length, i)
     end
          
   #test the ksubn private iteratyor returning in each iteration one k subset of an n element set
   def test_ksubn_iterator_should_provide_all_events_in_list
     filterset = EventSet.new()
     
     EventSet.publicize_methods do
        @e.ksubn_iterator(3) do |x|
        assert(@list.include?(x),"#{x.to_s} '\nnot in: \n#{@list.to_s}")
       end
     end
   end

  #test the private permutations method on a small example (integers)
  def test_permutations_small_should_return_permutations_of_1_and_2
    
    subsetlist = Array.new()
    subsetlist << 1
    subsetlist << 2

    resultlist = Array.new()
    resultlist << subsetlist
    newsubsetlist = Array.new()
    newsubsetlist << 2 << 1
    resultlist << newsubsetlist

    solutions = Array.new()
    EventSet.publicize_methods do
       solutions = @e.permutations(subsetlist)
       puts "solutions is #{solutions}" if $DEBUG
    end
    
    #The problem is that we cannot predict the permutation so we have to unshoft the array
    assert_equal(2, solutions.length)
    for item in resultlist
      assert(solutions.include?(item))
      solutions.delete(item)     
    end
    assert(solutions.empty?)


  end

  #test the private permutations method on real events and eventsets
  def test_permutations_should_return_permutations_of_events_e1_e2_and_e3
    
    subsetlist = Array.new()
    subsetlist << @e1
    subsetlist << @e2
    subsetlist << @e3

    resultlist = Array.new()
    resultlist << subsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e1 << @e3 << @e2
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e2 << @e1 << @e3
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e2 << @e3 << @e1
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e3 << @e1 << @e2
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e3 << @e2 << @e1
    resultlist << newsubsetlist

    solutions = Array.new()
    EventSet.publicize_methods do
       solutions = @e.permutations(subsetlist)
    end
    
    assert_equal(6, solutions.length)
    for item in resultlist
      assert(solutions.include?(item))
      solutions.delete(item)     
    end
    assert(solutions.empty?)
  end
  
  #test the private permutations method on a small example (integers)
  def test_fast_permutations_small_should_return_permutations_of_1_and_2
    
    subsetlist = Array.new()
    subsetlist << 1
    subsetlist << 2

    resultlist = Array.new()
    resultlist << subsetlist
    newsubsetlist = Array.new()
    newsubsetlist << 2 << 1
    resultlist << newsubsetlist

    solutions = Array.new()
    EventSet.publicize_methods do
       solutions = @e.fast_permutations(subsetlist)
       puts "solutions is #{solutions}" if $DEBUG
    end
    
    #The problem is that we cannot predict the permutation so we have to unshift the array
    assert_equal(2, solutions.length)
    for item in resultlist
      assert(solutions.include?(item))
      solutions.delete(item)     
    end
    assert(solutions.empty?)
  end

  #test the private permutations method on real events and eventsets
  def test_fast_permutations_should_return_permutations_of_events_e1_e2_and_e3
    
    subsetlist = Array.new()
    subsetlist << @e1
    subsetlist << @e2
    subsetlist << @e3

    resultlist = Array.new()
    resultlist << subsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e1 << @e3 << @e2
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e2 << @e1 << @e3
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e2 << @e3 << @e1
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e3 << @e1 << @e2
    resultlist << newsubsetlist
    newsubsetlist = Array.new()
    newsubsetlist << @e3 << @e2 << @e1
    resultlist << newsubsetlist

    solutions = Array.new()
    EventSet.publicize_methods do
       solutions = @e.fast_permutations(subsetlist)
    end
    
    assert_equal(6, solutions.length)
    for item in resultlist
      assert(solutions.include?(item))
      solutions.delete(item)     
    end
    assert(solutions.empty?)
  end    

end


class TestEventSetMethods < Test::Unit::TestCase
  def setup
    @e  = EventSet.new()
    @f  = EventSet.new()
    @e1 = Event.new(:nodeid => 3, :type => :send, :origin=> 1)
    @e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
    @e3 = Event.new(:nodeid => 3, :type => :send, :origin=> 3)
    @e.add(@e1)     #@e1 = Event.new(:nodeid => 3, :type => :send, :origin=> 1)
    @e.add(@e2)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
    @e.add(@e3)     #@e3 = Event.new(:nodeid => 3, :type => :send, :origin=> 3)

  end

  def test_select_returns_eventset
    result = EventSet.new
    EventSet.publicize_methods do
      result = @e.select {|event1| event1[:origin] < 1}
    end
    assert_equal(@e.class, result.class)
  end

  def test_select_empty
    result = EventSet.new
    EventSet.publicize_methods do    
      result = @e.select {|event1| event1[:origin] < 1}
    end
    assert(result.empty?)
  end

  def test_select_empty_input
    emptyset = EventSet.new
    result = EventSet.new
    EventSet.publicize_methods do
      result = emptyset.select {|event1| event1[:origin] < 1}
    end
    assert(result.empty?)
  end

  
  def test_select_simple
    result = EventSet.new
    f = EventSet.new
    f.add(@e3)
    EventSet.publicize_methods do        
      result = @e.select {|event1| event1[:origin] == 3}
    end
    assert_equal(f, result)
  end

  def test_select_all
    result = EventSet.new    
    EventSet.publicize_methods do     
     result = @e.select {|event1| event1[:origin] < 5}
    end
    assert_equal(
    @e, result)
  end
  
  
  #test simple filtering with the predicate method
   def test_predicate_filter_should_return_all_event_combinations_except_e2_e3_since_they_do_not_satisfy_predicate
     matched = Array.new()
     f1 = Array.new()
     f1 << @e1
     f1 << @e3
     matched << f1
     f2 = Array.new()
     f2 << @e1 
     f2 << @e2
     matched << f2
     f3 = Array.new()
     f3 << @e3
     f3 << @e1
     matched << f3
     f4 = Array.new()
     f4 << @e2 
     f4 << @e1
     matched << f4
     result1 = @e.predicate(2) {|event1, event2| event1[:origin] + event2[:origin] <= 4}

     result1[:matched].each do |x|
        a =  x.to_s()
        if $DEBUG
          puts "x.to_s is:"
          puts x.to_s
        end
        assert(matched.include?(x),"#{a} \nnot in expected results")
        matched.delete(x)         
     end
     assert(result1[:unmatched].empty?, "#{result1[:unmatched]} is not empty")
     assert(matched.empty?)
   end
    
    #test selecting all events with the predicate method
   def test_predicate_no_filter_should_return_all_events_since_all_satisfy_predicate  
     matched = Array.new()
     f1 = Array.new()
     f1 << @e1
     f1 << @e3
     matched << f1
     f2 = Array.new()
     f2 << @e1
     f2 << @e2
     matched << f2
     f3 = Array.new()
     f3 << @e2
     f3 << @e3
     matched << f3
     f4 = Array.new()
     f4 << @e3
     f4 << @e1
     matched << f4
     f5 = Array.new()
     f5 << @e2
     f5 << @e1
     matched << f5
     f6 = Array.new()
     f6 << @e3
     f6 << @e2
     matched << f6
     result2 = @e.predicate(2) {|event1, event2| event1[:origin] + event2[:origin] <= 10}

     result2[:matched].each do |x|
        assert(matched.include?(x),"#{x.to_s} '\nnot in: \n#{matched.to_s}")
        matched.delete(x)         
     end
     
     assert(result2[:unmatched].empty?)
     assert(matched.empty?)

   end
   
   #test the predicate that returns an emptyset for matches
   def test_predicate_empty_set_should_return_empty_array_since_none_is_selected
     emptyArrayOfEventSet = Array.new()
     resultempty = @e.predicate(3) {|event1, event2, event3| event1[:type]==:send and event2[:type] == :receive and event3['something']}
 
     assert_equal(@e, resultempty[:unmatched])
     assert_equal(emptyArrayOfEventSet, resultempty[:matched])
   end

   #test the predicate that returns an emptyset for matches
   def test_predicate_empty_set_should_return_empty_array_since_input_is_empty
     emptyEventSet = EventSet.new
     emptyArrayOfEventSet = Array.new()
     resultempty = emptyEventSet.predicate(3) {|event1, event2, event3| event1[:type]==:send and event2[:type] == :receive and event3['something']}

     assert_equal(emptyEventSet, resultempty[:unmatched])
     assert_equal(emptyArrayOfEventSet, resultempty[:matched])
   end
   
   #test the predicate that works on a minimal event set thus only possible to return a single element
   def test_predicate_single_element_should_return_all_single_events
     @f.add(@e1)     #@e1 = Event.new(:nodeid => 3, :type => :send, :origin=> 1)
     @f.add(@e2)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
     matched = Array.new()
     f1 = EventSet.new()
     f1.add(@e1)
     matched << f1
     f2 = EventSet.new()
     f2.add(@e2)
     matched << f2

     result3 = @f.predicate(1) {|event1| event1[:nodeid] == 3}
     result3[:matched].each do |x|
        assert(matched.include?(x),"#{x.to_s} \nnot in: \n#{matched.to_s}")
        matched.delete(x)         
     end
     assert(result3[:unmatched].empty?)
     assert(matched.empty?)
   end

   def test_predicate_does_use_shallow_copy_and_should_return_modifications_on_original_set

     result2 = @e.predicate(2) {|event1, event2| event1[:origin] + event2[:origin] <= 10}
     result2[:matched].each do |x|
       x.each {|event| event[:notice]='success'}
     end
     assert_equal(@e.length, @e[:notice].length)
     
   end
      
   #test the deep clone method by simple comparison after modifying entries
   def test_deep_clone_should_return_deep_cloned_events_which_are_not_equal_to_the_new_ones
     @f = @e.deep_clone
     assert_not_same(@f, @e)
   end 

   #test the deep clone method by simple comparision without any modification
   def test_deep_clone_compare_should_return_equal_since_they_have_the_same_content
     @f = @e.deep_clone
     assert_equal(@f, @e)
   end 
      
 end  
class TestEventSetTansform < Test::Unit::TestCase
  def setup
    @e  = EventSet.new()
    @f  = EventSet.new()
    @e1 = Event.new(:nodeid => 3, :type => :send, :origin=> 1)
    @e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
    @e3 = Event.new(:nodeid => 3, :type => :send, :origin=> 3)
    @e.add(@e1)     #@e1 = Event.new(:nodeid => 3, :type => :send, :origin=> 1)
    @e.add(@e2)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
    @e.add(@e3)     #@e3 = Event.new(:nodeid => 3, :type => :send, :origin=> 3)
    @temp = @e.predicate(2) {|event1, event2| event1[:origin] + event2[:origin] == 4 and event1[:origin] == 1}
    @temp2 = @e.predicate(1) {|event1| event1[:origin] >= 1}
    @single = @e.predicate(1) {|event1| event1[:origin] == 1}
    @empty = @e.predicate(1) {|event1| event1[:origin] < 1}    
  end   
   
   #test transform method merging two into one event
   def test_merge_transform_should_return_single_merged_event_per_match_which_is_combination_of_1_and_3
     result = @e.set_transform(@temp, :merge, 2) do |event1, event2|
     {
       :nodeid => event1[:nodeid],
       :type => event1[:type],
       :origin => event1[:origin] + event2[:origin]
     }
     end
     @f.add(@e2)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
     newevent = Event.new(:nodeid => 3, :type => :send, :origin=> 4)
     @f.add(newevent)
     assert_equal(@f, result)
   end

   #test transform method merging two into two events   
   def test_multi_merge_transform_should_return_two_merged_events_per_match_which_are_combinations_of_1_and_3
     result = @e.set_transform(@temp, :merge, 2) do |event1, event2|
      [ 
         {
         :nodeid => event1[:nodeid],
         :type => event1[:type],
         :origin => event1[:origin] +10
       } ,
       {
         :nodeid => event2[:nodeid],
         :type => event2[:type],
         :origin => event2[:origin] + 10
       }
     ]
     end
     @f.add(@e2)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
     newevent1= Event.new(:nodeid => 3, :type => :send, :origin=> 11)
     newevent2 = Event.new(:nodeid => 3, :type => :send, :origin=> 13)

     @f.add(newevent1)
     @f.add(newevent2)     
     assert_equal(@f, result)
   end

   #test transform method creating a new event (maintaining the old) from two events   
   def test_create_transform_should_return_single_new_event_per_match_which_is_combination_of_1_and_3
     result = @e.set_transform(@temp, :create, 2) do |event1, event2|
     {
       :nodeid => event1[:nodeid],
       :type => event1[:type],
       :origin => event1[:origin] + event2[:origin]
     }
     end
     @f.add(@e1)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
     @f.add(@e2)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)
     @f.add(@e3)     #@e2 = Event.new(:nodeid => 3, :type => :send, :origin=> 2)     
     newevent = Event.new(:nodeid => 3, :type => :send, :origin=> 4)
     @f.add(newevent)
     assert_equal(@f, result)
   end
   
   #test transform method merging on a single event   
   def test_merge_transform_on_a_single_event_should_return_one_single_event
     result = @e.set_transform(@temp2, :merge, 1) do |event1|
     {
       :nodeid => event1[:nodeid],
       :type => :new_type,
       :origin => event1[:origin]
     }
     end
     newevent1 = Event.new(:nodeid => 3, :type => :new_type, :origin=> 1)
     newevent2 = Event.new(:nodeid => 3, :type => :new_type, :origin=> 2)
     newevent3 = Event.new(:nodeid => 3, :type => :new_type, :origin=> 3)    
     @f.add(newevent1)
     @f.add(newevent2)
     @f.add(newevent3)          
     assert_equal(@f, result)
   end
      
   #test transform method merging on a single event with single event as input
   def test_merge_transform_on_a_single_event_with_only_single_event_as_input_should_return_one_single_event
     result = @e.set_transform(@single, :merge, 1) do |event1|
     {
       :nodeid => event1[:nodeid],
       :type => :new_type,
       :origin => event1[:origin]
     }
     end
     @f.add(@e2)
     @f.add(@e3)
     newevent = Event.new(:nodeid => 3, :type => :new_type, :origin=> 1)
     @f.add(newevent)
     assert_equal(@f, result)
   end

   #test transform method merging on a single event with single event as input
   def test_merge_transform_on_a_single_event_with_only_single_event_as_input_should_return_one_single_event
     result = @e.set_transform(@empty, :merge, 1) do |event1|
     {
       :nodeid => event1[:nodeid],
       :type => :new_type,
       :origin => event1[:origin]
     }
     end
     @f.add(@e1)
     @f.add(@e2)
     @f.add(@e3)
     assert_equal(@f, result)
   end

end
    
class TestEventSetComposite < Test::Unit::TestCase
  def setup
    @e  = EventSet.new()
    @f  = EventSet.new()
    @send1 = Event.new(:nodeid => 3, :type => :send, :origin=> 1, :destination=>4)
    @send2 = Event.new(:nodeid => 4, :type => :send, :origin=> 1, :destination=>5)
    @send3 = Event.new(:nodeid => 5, :type => :send, :origin=> 1, :destination=>20)
    @receive1 = Event.new(:nodeid => 4, :type => :receive, :origin=> 1, :destination=>4)
    @receive2 = Event.new(:nodeid => 5, :type => :receive, :origin=> 1, :destination=>5)
    @receive3 = Event.new(:nodeid => 20, :type => :receive, :origin=> 1, :destination=>20)
    @e.merge([@send1, @send2, @send3, @receive1, @receive2, @receive3])

  end      
  
  #composite predicate and transform as used in EvAnT: Two selected and one merged event
  def test_merge_transform_composite    
     temp = @e.predicate(2) {|e1, e2| e1[:origin] == e2[:origin] and e1[:type] == :send and \
       e2[:type] == :receive and e1[:destination] == e2[:nodeid]}

     result = @e.set_transform(temp, :merge, 2) do |e1, e2|
     {
       :nodeid => e2[:nodeid],
       :type => :transmission,
       :origin => e1[:origin]
     }
     end
     
     if $DEBUG
       puts "After the predicate selection we have" 
       temp[:matched].each do |printval| 
         puts "Element:"
         puts printval
      end
       puts "result is"
       puts result
     end
     newevent1 = Event.new(:nodeid => 4, :type => :transmission, :origin=> 1)
     newevent2 = Event.new(:nodeid => 5, :type => :transmission, :origin=> 1)
     newevent3 = Event.new(:nodeid => 20, :type => :transmission, :origin=> 1)
     @f.add(newevent1)
     @f.add(newevent2)
     @f.add(newevent3)
     assert_equal(@f, result)
  end

end
    
class TestEventSetIterative < Test::Unit::TestCase
  def setup

    @g  = EventSet.new()
    @send2 = Event.new(:nodeid => 4, :type => :send, :origin=> 3, :destination=>5, :time => 10)
    @send3 = Event.new(:nodeid => 5, :type => :send, :origin=> 3, :destination=>20, :time => 10)
    @receive1 = Event.new(:nodeid => 4, :type => :receive, :origin=> 3, :destination=>4, :time => 11)
    @receive2 = Event.new(:nodeid => 5, :type => :receive, :origin=> 3, :destination=>5, :time => 11)
    @receive3 = Event.new(:nodeid => 20, :type => :receive, :origin=> 3, :destination=>20, :time => 12)
    @receive4 = Event.new(:nodeid => 20, :type => :receive, :origin=> 3, :destination=>20, :time => 12)
    @receive5 = Event.new(:nodeid => 20, :type => :receive, :origin=> 3, :destination=>20, :time => 13)    
    @send1_mod = Event.new(:nodeid => 3, :type => :transmission, :origin=> 3, :destination=>4)
    @g.merge([@send1_mod, @send2, @send3, @receive1, @receive2, @receive3])

    @finalset = EventSet.new()
    @finalmerged = Event.new(:nodeid => 20, :type => :transmission, :origin=> 3, :destination=>20)
    @finalset.add(@finalmerged)
    
    @finalmerged_dup1 = Event.new(:nodeid => 20, :type => :transmission, :origin=> 3, :destination=>20, :time=>12)
    @finalmerged_dup2 = Event.new(:nodeid => 20, :type => :transmission, :origin=> 3, :destination=>20, :time=>13)
        
    @dupset = EventSet.new()        
    @dupset.add(@finalmerged_dup1)
    @dupset.add(@finalmerged_dup2)
  end

  
  def test_iterative_start_cond_without_block_should_do_nothing
     assert_nothing_raised{
       @g = @g.iterative
     }

  end     
  #composite predicate and transform as used in Fixed point processor in EvAnT: Two selected and one merged event  
  def test_iterative_start_cond_should_return_a_processed_set_and_assert_that_only_the_minimal_amount_of_iterations_is_taken
    
    #TODO: Fails when running all tests, but runs in isolated test
     i=0
   resultset = @g.iterative do |iteration|
     temp = iteration.predicate(2) {|e1, e2| e1[:origin] == e2[:origin] and ((e1[:type] == :transmission and \
     e2[:type] == :receive and e1[:destination] == e2[:nodeid]) or (e1[:nodeid] == e2[:nodeid] and \
     e1[:type] == :transmission and e2[:type] == :send))
     }
     i += 1
     iteration.set_transform(temp, :merge, 2) do |e1, e2|
     {
       :nodeid => e2[:nodeid],
       :type => :transmission,
       :origin => e1[:origin],
       :destination => e2[:destination]
     }
     end
   end
   assert_equal(6, i)
   assert_equal(@finalset, resultset)
  end   

  #composite predicate and transform as used in Fixed point processor in EvAnT: Two selected and one merged event  
  def test_iterative_start_should_return_a_set_without_duplicates_but_with_double_association_for_differences
    
    #TODO: Fails when running all tests, but runs in isolated test
        
    @g.merge([@receive4, @receive5])    

   resultset = @g.iterative do |iteration|
     temp = iteration.predicate(2) {|e1, e2| e1[:origin] == e2[:origin] and ((e1[:type] == :transmission and \
     e2[:type] == :receive and e1[:destination] == e2[:nodeid]) or (e1[:nodeid] == e2[:nodeid] and
     e1[:type] == :transmission and e2[:type] == :send))
     }

     iteration.set_transform(temp, :merge, 2) do |e1, e2|
     {
       :nodeid => e2[:nodeid],
       :type => :transmission,
       :origin => e1[:origin],
       :destination => e2[:destination],
       :time => e2[:time]
     }
     end
   end

   assert_equal(@dupset, resultset)
  end
end